home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 November / PCWorld_2006-11_cd.bin / domacnost a kancelar / findgraph / fgraph.exe / {app} / TestVC / MainView.cpp < prev    next >
C/C++ Source or Header  |  2002-11-21  |  43KB  |  1,678 lines

  1. // MainView.cpp : implementation of the CMainView class
  2. //
  3. // From MFC\OLE\OCLIENT
  4. //     
  5. ///////////////////////////////////////////////////////////////
  6. // How to realise automation FindGraph.
  7. // 1. Create IFindGraph wrapper class from a type FindGraph.tlb.
  8. // 2. Add #include "FindGraph.h".
  9. //
  10. // 3. Add to CRectItem:
  11. //               LPDISPATCH GetIDispatch();
  12. //    This returns IDispatch* for embedded application
  13. //    see sample from MSDN: HOWTO: IQ: Q184663 for details.
  14. //
  15. // 4. Call FindGraphs's methods as wrapper:
  16. //        DECLARE_FINDGRAPHS(FindGraph);
  17. //        FindGraph.ReleaseDispatch();
  18. //
  19. //
  20. //
  21. //
  22. //
  23. //
  24. ///////////////////////////////////////////////////////////////
  25. //
  26. // How to use Crov
  27. // 1. Run Crov.exe.
  28. // 2. Push button "Insert FindGraph"
  29. //    or select menu item <Edit><Insert FindGraph>.
  30. // 3. FindGraph plot will appear as embedded object.
  31. // 4. Deactivate it. To do this click on Crov work area.
  32. // 5. Message Box will appear: Document was not saved. Save changes?
  33. //    Select to save.
  34. // 6. Activate FindGraph embedded object.
  35. //    To do this click once on FindGraph object.
  36. // 9. Toolbar FindGraph buttons will become enabled.
  37. //10. Push button "Add new points"
  38. //    or select menu item <FindGraph><Add points>.
  39. //
  40. ///////////////////////////////////////////////////////////////
  41.  
  42.  
  43. #include "stdafx.h"
  44. #include "Crov.h"
  45.  
  46. #include "MainFrm.h"
  47. #include "MainDoc.h"
  48. #include "RectItem.h"
  49. #include "MainView.h"
  50.  
  51. #include "FindGraph.h"
  52. #include <math.h>
  53.  
  54. #ifdef _DEBUG
  55. #define new DEBUG_NEW
  56. #undef THIS_FILE
  57. static char THIS_FILE[] = __FILE__;
  58. #endif
  59.  
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CMainView
  62. CBrush NEAR CMainView::m_brHatch;
  63. CLIPFORMAT CMainView::m_cfObjectDescriptor=NULL;
  64.  
  65.  
  66.  
  67. IMPLEMENT_DYNCREATE(CMainView, CScrollView)
  68.  
  69. BEGIN_MESSAGE_MAP(CMainView, CScrollView)
  70.     //{{AFX_MSG_MAP(CMainView)
  71.     ON_WM_DESTROY()
  72.     ON_WM_SETFOCUS()
  73.     ON_WM_SIZE()
  74.     ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
  75.     ON_COMMAND(ID_CANCEL_EDIT_CNTR, OnCancelEditCntr)
  76.     ON_WM_LBUTTONDBLCLK()
  77.     ON_WM_LBUTTONDOWN()
  78.     ON_WM_SETCURSOR()
  79.     ON_WM_CREATE()
  80.     ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  81.     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  82.     ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  83.     ON_COMMAND(ID_EDIT_PASTE, OnPaste)
  84.     ON_COMMAND(ID_OBJECT_RESETSIZE, OnObjectResetsize)
  85.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateEditMenu)
  86.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  87.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)
  88.     ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)
  89.     ON_WM_RBUTTONDOWN()
  90.     ON_COMMAND(ID_EDIT_PASTE_INVIEW, OnEditPasteInview)
  91.     ON_WM_MOUSEMOVE()
  92.     ON_COMMAND(ID_VIEW_NET, OnViewNet)
  93.     ON_UPDATE_COMMAND_UI(ID_VIEW_NET, OnUpdateViewNet)
  94.     ON_COMMAND(ID_INSERT_FINDGRAPH, OnInsertFindGraph)
  95.     ON_COMMAND(ID_ITEM_DOTS, OnItemDots)
  96.     ON_UPDATE_COMMAND_UI(ID_ITEM_DOTS, OnUpdateItemDots)
  97.     ON_COMMAND(ID_ITEM_DOTSGET, OnItemDotsget)
  98.     ON_COMMAND(ID_ITEM_FINDGRAPH, OnItemFindGraphProp)
  99.     ON_UPDATE_COMMAND_UI(ID_ITEM_DOTSGET, OnUpdateItemDots)
  100.     ON_UPDATE_COMMAND_UI(ID_ITEM_FINDGRAPH, OnUpdateItemDots)
  101.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_INVIEW, OnUpdateEditPaste)
  102.     ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditMenu)
  103.     ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditMenu)
  104.     ON_UPDATE_COMMAND_UI(ID_OBJECT_RESETSIZE, OnUpdateEditMenu)
  105.     ON_COMMAND(ID_INSERT_EXCEL, OnInsertExcel)
  106.     //}}AFX_MSG_MAP
  107.     // Standard printing commands
  108.     ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  109.     ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
  110.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  111. END_MESSAGE_MAP()
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // CMainView construction/destruction
  115.  
  116. CMainView::CMainView()
  117. {
  118.     if (m_brHatch.m_hObject == NULL)
  119.         m_brHatch.CreateHatchBrush(HS_DIAGCROSS, RGB(0,0,0));
  120.  
  121.     if (m_cfObjectDescriptor == NULL)
  122.         m_cfObjectDescriptor =
  123.             (CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor"));
  124.  
  125.     m_bIsNet = true;
  126.     m_pSelection = NULL;
  127.     m_prevDropEffect = DROPEFFECT_NONE;
  128.     m_bInDrag = FALSE;
  129.     m_dwIdDots = -1;
  130. }
  131.  
  132. CMainView::~CMainView()
  133. {
  134. }
  135.  
  136. BOOL CMainView::PreCreateWindow(CREATESTRUCT& cs)
  137. {
  138.     // TODO: Modify the Window class or styles here by modifying
  139.     //  the CREATESTRUCT cs
  140.  
  141.     return CScrollView::PreCreateWindow(cs);
  142. }
  143.  
  144. void CMainView::OnDestroy()
  145. {
  146.     // Deactivate the item on destruction; this is important
  147.     // when a splitter view is being used.
  148.    CScrollView::OnDestroy();
  149.    COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  150.    if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
  151.    {
  152.       pActiveItem->Deactivate();
  153.       ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  154.    }
  155. }
  156.  
  157. void CMainView::OnInitialUpdate()
  158. {
  159.     CScrollView::OnInitialUpdate();
  160.  
  161.  
  162.     // We can't pass MM_ANISOTROPIC to SetScrollSizes so we have to convert to MM_TEXT
  163.     CSize size = GetDocument()->GetDocumentSize();
  164.     CClientDC dc(NULL);
  165.     size.cx = MulDiv(size.cx, dc.GetDeviceCaps(LOGPIXELSX), 100);
  166.     size.cy = MulDiv(size.cy, dc.GetDeviceCaps(LOGPIXELSY), 100);
  167.     SetScrollSizes(MM_TEXT, size);
  168. }
  169.  
  170.  
  171. /////////////////////////////////////////////////////////////////////////////
  172. // CMainView drawing
  173. void CMainView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  174. {
  175.     CScrollView::OnPrepareDC(pDC, pInfo);
  176.     // set up a reasonable default context
  177.     pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
  178.     pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
  179.  
  180.     // LOENGLISH units are based on physical inches
  181.     // We want logical inches so we have to do it differently
  182.     pDC->SetMapMode(MM_ANISOTROPIC);
  183.     pDC->SetViewportExt(
  184.         pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
  185.     pDC->SetWindowExt(100,-100);
  186. }
  187.  
  188. void CMainView::SetupTracker(CRectTracker* pTracker, CRectItem* pItem,
  189.     CRect* pTrueRect)
  190. {
  191.     ASSERT(pTracker != NULL);
  192.     ASSERT(pItem != NULL);
  193.  
  194.     pTracker->m_rect = pItem->GetRect();
  195.     DocToClient(pTracker->m_rect);
  196.  
  197.     // set minimum size for our OLE items
  198.     pTracker->m_sizeMin.cx = 8;
  199.     pTracker->m_sizeMin.cy = 8;
  200.  
  201.     pTracker->m_nStyle = 0;
  202.  
  203.     // setup resize handles if item is selected
  204.     if (pItem == m_pSelection)
  205.         pTracker->m_nStyle |= CRectTracker::resizeInside;
  206.  
  207.     // put correct border depending on item type
  208.     if (pItem->GetType() == OT_LINK)
  209.         pTracker->m_nStyle |= CRectTracker::dottedLine;
  210.     else
  211.         pTracker->m_nStyle |= CRectTracker::solidLine;
  212.  
  213.     // put hatching over the item if it is currently open
  214.     if (pItem->GetItemState() == COleClientItem::openState ||
  215.         pItem->GetItemState() == COleClientItem::activeUIState)
  216.     {
  217.         pTracker->m_nStyle |= CRectTracker::hatchInside;
  218.     }
  219.  
  220.     if (pTrueRect != NULL)
  221.         pTracker->GetTrueRect(pTrueRect);
  222. }
  223. void CMainView::OnDraw(CDC* pDC)
  224. {
  225.     CMainDoc* pDoc = GetDocument();
  226.     ASSERT_VALID(pDoc);
  227.  
  228.     
  229.     // TODO: add draw code for native data here
  230.     // TODO: also draw all OLE items in the document
  231.     if (!pDC->IsPrinting())
  232.     {
  233.         m_brHatch.UnrealizeObject();
  234.         CPoint point(0, 0);
  235.         pDC->LPtoDP(&point);
  236.         pDC->SetBrushOrg(point.x % 8, point.y % 8);
  237.  
  238.         CRect rcClip;
  239.         GetClientRect(&rcClip);
  240.         ClientToDoc(rcClip);
  241.         CSize docSize = pDoc->GetDocumentSize();
  242.         if (rcClip.right > docSize.cx)
  243.         {
  244.             CRect rcFill(rcClip);
  245.             rcFill.left = max(rcFill.left,docSize.cx);
  246.             pDC->FillRect(rcFill,&m_brHatch);
  247.         }
  248.         if (rcClip.bottom < -docSize.cy)
  249.         {
  250.             CRect rcFill(rcClip);
  251.             rcFill.top = min(rcFill.top, -docSize.cy);
  252.             pDC->FillRect(rcFill,&m_brHatch);
  253.         }
  254.         if (m_bIsNet)
  255.         {
  256.             CPen  pen(PS_DOT, 1, RGB(128,128,128));
  257.             CPen *pen0 = pDC->SelectObject(&pen);
  258.             double  dx=100/2.54,
  259.                     dy=100/2.54;
  260.             int  x, y, i;
  261.             for (i=0, x=1; x < docSize.cx; i++)
  262.             {
  263.                 x=1+(int)(dx*i);
  264.                 pDC->MoveTo(x, 0);
  265.                 pDC->LineTo(x, -docSize.cy);
  266.             }
  267.             for (i=0, y=-1; y>-docSize.cy; i++)
  268.             {
  269.                 y=-1-(int)(dy*i);
  270.                 pDC->MoveTo(0, y);
  271.                 pDC->LineTo(docSize.cx, y);
  272.             }
  273.             pDC->SelectObject(pen0);
  274.         }
  275.     }
  276.  
  277.     // Draw all the CRectItems
  278.     POSITION pos = pDoc->GetStartPosition();
  279.     while (pos != NULL)
  280.     {
  281.         CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
  282.         if (pItem != NULL)
  283.         {
  284.             pItem->Draw(pDC, pItem->GetRect());
  285.  
  286.             if (!pDC->IsPrinting())
  287.             {
  288.                 // draw the tracker
  289.                 CRectTracker tracker;
  290.                 CRect rectTrue;
  291.                 SetupTracker(&tracker, pItem, &rectTrue);
  292.                 ClientToDoc(rectTrue);
  293.                 if (pDC->RectVisible(&rectTrue))
  294.                     tracker.Draw(pDC);
  295.             }
  296.         }
  297.     }
  298. }
  299.  
  300.  
  301. void CMainView::InvalidateItem(CRectItem* pItem)
  302. {
  303.     if (m_nMapMode != 0)
  304.     {
  305.         CRectTracker tracker;
  306.         CRect rect;
  307.         SetupTracker(&tracker, pItem, &rect);
  308.         InvalidateRect(&rect);
  309.     }
  310. }
  311.  
  312.  
  313.  
  314.  
  315. /////////////////////////////////////////////////////////////////////////////
  316. // Hit detection, moving and resizing items
  317.  
  318. CRectItem* CMainView::GetHitItem(CPoint point)
  319. {
  320.     CMainDoc* pDoc = GetDocument();
  321.     CRectItem* pItemHit = NULL;
  322.  
  323.     // Find the item hit by the mouse
  324.     POSITION pos = pDoc->GetStartPosition();
  325.     while (pos != NULL)
  326.     {
  327.         CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
  328.         if (pItem != NULL)
  329.         {
  330.             CRectTracker tracker;
  331.             SetupTracker(&tracker, pItem);
  332.             if (tracker.HitTest(point) >= 0)
  333.             {
  334.                 pItemHit = pItem;
  335.                 // items later in the list are drawn on top - so keep looking
  336.             }
  337.         }
  338.     }
  339.     return pItemHit;
  340. }
  341.  
  342. void CMainView::DocToClient(CRect& rect)
  343. {
  344.     CClientDC dc(this);
  345.     OnPrepareDC(&dc);
  346.     dc.LPtoDP(&rect); // convert logical rect to device rect
  347.     rect.NormalizeRect();
  348. }
  349.  
  350. void CMainView::ClientToDoc(CRect& rect)
  351. {
  352.     CClientDC dc(this);
  353.     OnPrepareDC(&dc);
  354.     dc.DPtoLP(&rect); // convert device rect to logical rect
  355. }
  356.  
  357. void CMainView::DocToClient(CSize& size)
  358. {
  359.     CClientDC dc(this);
  360.     OnPrepareDC(&dc);
  361.     dc.LPtoDP(&size); // convert logical size to device size
  362.     size.cx = abs(size.cx);
  363.     size.cy = abs(size.cy);
  364. }
  365.  
  366. void CMainView::ClientToDoc(CSize& size)
  367. {
  368.     CClientDC dc(this);
  369.     OnPrepareDC(&dc);
  370.     dc.DPtoLP(&size); // convert device rect to logical rect
  371.     size.cx = abs(size.cx);
  372.     size.cy = abs(size.cy);
  373. }
  374.  
  375. void CMainView::DocToClient(CPoint& point)
  376. {
  377.     CClientDC dc(this);
  378.     OnPrepareDC(&dc);
  379.     dc.LPtoDP(&point); // convert logical point to device point
  380. }
  381.  
  382. void CMainView::ClientToDoc(CPoint& point)
  383. {
  384.     CClientDC dc(this);
  385.     OnPrepareDC(&dc);
  386.     dc.DPtoLP(&point); // convert device point to logical point
  387. }
  388.  
  389.  
  390. /////////////////////////////////////////////////////////////////////////////
  391. // Selection support
  392.  
  393. BOOL CMainView::IsSelected(const CObject* pDocItem) const
  394. {
  395.     return (pDocItem == m_pSelection);
  396. }
  397.  
  398. void CMainView::SetSelection(CRectItem* pNewSel, BOOL bSafeSelect)
  399. {
  400.     if (pNewSel != NULL && pNewSel == m_pSelection)
  401.         return;
  402.  
  403.     // deactivate any in-place active item on this view!
  404.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  405.     if (pActiveItem != NULL && pNewSel != pActiveItem)
  406.     {
  407.         if (bSafeSelect)
  408.             return;
  409.         // if we found one, deactivate it
  410.         pActiveItem->Close();
  411.         ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  412.     }
  413.     if (m_pSelection != NULL) // invalidate the old item
  414.         InvalidateItem(m_pSelection);
  415.     if ((m_pSelection = pNewSel) != NULL) // invalidate the new item
  416.         InvalidateItem(m_pSelection);
  417. }
  418.  
  419. /////////////////////////////////////////////////////////////////////////////
  420. void CMainView::UpdateActiveItem()
  421. {
  422.     // when there is an active item visible, sizing the window may cause
  423.     //  more/less of the in-place object to become visible.
  424.     //  (ie. the clipping rectangle changes with the size of the window)
  425.     // a container supporting scrolling would also have to do this
  426.     //  when scrolling the contents of the window.
  427.  
  428.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  429.     if (pActiveItem != NULL &&
  430.         pActiveItem->GetItemState() == COleClientItem::activeUIState &&
  431.         pActiveItem->GetActiveView() == this)
  432.     {
  433.         // this will update the item rectangles by calling
  434.         //  OnGetPosRect & OnGetClipRect.
  435.         pActiveItem->SetItemRects();
  436.     }
  437. }
  438. /////////////////////////////////////////////////////////////////////////////
  439. // OLE Client support and commands
  440.  
  441. void CMainView::OnInsertObject()
  442. {
  443.     COleInsertDialog dlg;
  444.     if (dlg.DoModal() != IDOK)
  445.         return;
  446.  
  447.     BeginWaitCursor();
  448.  
  449.     CRectItem* pItem = NULL;
  450.     TRY
  451.     {
  452.         // create item from dialog results
  453.         pItem = GetDocument()->CreateItem();
  454.         if (!dlg.CreateItem(pItem))
  455.             AfxThrowMemoryException();  // any exception will do
  456.  
  457.         // try to get initial presentation data
  458.         pItem->UpdateLink();
  459.         pItem->UpdateExtent();
  460.  
  461.         // if insert new object -- initially show the object
  462.         if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
  463.             pItem->DoVerb(OLEIVERB_SHOW, this);
  464.  
  465.         SetSelection(pItem);
  466.     }
  467.     CATCH_ALL(e)
  468.     {
  469.         // cleanup item, if allocated
  470.         if (pItem != NULL)
  471.             GetDocument()->DeleteItem(pItem);
  472.  
  473.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  474.     }
  475.     END_CATCH_ALL
  476.  
  477.     EndWaitCursor();
  478. }
  479.  
  480. // The following command handler provides the standard keyboard
  481. //  user interface to cancel an in-place editing session.  Here,
  482. //  the container (not the server) causes the deactivation.
  483. void CMainView::OnCancelEditCntr()
  484. {
  485.     // Close any in-place active item on this view.
  486.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  487.     if (pActiveItem != NULL)
  488.     {
  489.         pActiveItem->Close();
  490.     }
  491.     ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  492. }
  493.  
  494. void CMainView::OnRButtonDown(UINT nFlags, CPoint point) 
  495. {
  496.     // make sure window is active
  497.     GetParentFrame()->ActivateFrame();
  498.  
  499.     SetSelection(GetHitItem(point));    // reselect item if appropriate
  500.     UpdateWindow();
  501.  
  502.     UINT nID = ID_OBJECT_POPUP_MENU;
  503.     if (m_pSelection == NULL) 
  504.     {
  505.         nID = ID_VIEW_POPUP_MENU;
  506.         m_pointMouse = point;
  507.         ClientToDoc(m_pointMouse);
  508.     }
  509.     CMenu bar;
  510.     if (bar.LoadMenu(nID))
  511.     {
  512.         CMenu& popup = *bar.GetSubMenu(0);
  513.         ASSERT(popup.m_hMenu != NULL);
  514.  
  515.         ClientToScreen(&point);
  516.         popup.TrackPopupMenu(TPM_RIGHTBUTTON, point.x, point.y,    AfxGetMainWnd());
  517.     }
  518. }
  519.  
  520.  
  521. // Special handling of OnSetFocus and OnSize are required for a container
  522. //  when an object is being edited in-place.
  523. void CMainView::OnSetFocus(CWnd* pOldWnd)
  524. {
  525.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  526.     if (pActiveItem != NULL &&
  527.         pActiveItem->GetItemState() == COleClientItem::activeUIState)
  528.     {
  529.         // need to set focus to this item if it is in the same view
  530.         CWnd* pWnd = pActiveItem->GetInPlaceWindow();
  531.         if (pWnd != NULL)
  532.         {
  533.             pWnd->SetFocus();
  534.             return;
  535.         }
  536.     }
  537.     CScrollView::OnSetFocus(pOldWnd);
  538. }
  539.  
  540. void CMainView::OnSize(UINT nType, int cx, int cy)
  541. {
  542.     CScrollView::OnSize(nType, cx, cy);
  543.     UpdateActiveItem();
  544. }
  545.  
  546. /////////////////////////////////////////////////////////////////////////////
  547. // CMainView diagnostics
  548.  
  549. #ifdef _DEBUG
  550. void CMainView::AssertValid() const
  551. {
  552.     CScrollView::AssertValid();
  553. }
  554.  
  555. void CMainView::Dump(CDumpContext& dc) const
  556. {
  557.     CScrollView::Dump(dc);
  558. }
  559.  
  560.  
  561. #endif //_DEBUG
  562. /////////////////////////////////////////////////////////////////////////////
  563. // CMainView printing
  564.  
  565. BOOL CMainView::OnPreparePrinting(CPrintInfo* pInfo)
  566. {
  567.     // default preparation
  568.     return DoPreparePrinting(pInfo);
  569. }
  570.  
  571. void CMainView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  572. {
  573.     // TODO: add extra initialization before printing
  574. }
  575.  
  576. void CMainView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  577. {
  578.     // TODO: add cleanup after printing
  579. }
  580. /////////////////////////////////////////////////////////////////////////////
  581. // CMainView message handlers
  582.  
  583.  
  584.  
  585. void CMainView::OnLButtonDblClk(UINT nFlags, CPoint point) 
  586. {
  587.     // Double click will activate the main verb
  588.     if (m_pSelection != NULL)
  589.     {
  590.         BeginWaitCursor();
  591.         LONG iVerb = OLEIVERB_PRIMARY;
  592.         if (GetKeyState(VK_CONTROL) < 0)
  593.             iVerb = OLEIVERB_OPEN;
  594.         m_pSelection->DoVerb(iVerb, this);
  595.         EndWaitCursor();
  596.     }    
  597.     CScrollView::OnLButtonDblClk(nFlags, point);
  598. }
  599.  
  600. void CMainView::OnLButtonDown(UINT nFlags, CPoint point) 
  601. {
  602.     CRectItem* pItemHit = GetHitItem(point);
  603.     SetSelection(pItemHit);
  604.     if (pItemHit == NULL)
  605.         return;
  606.  
  607.     CRect rectLimit;
  608.     GetClientRect(rectLimit);
  609.  
  610.     CRectTracker tracker;
  611.     SetupTracker(&tracker, pItemHit);
  612.  
  613.     UpdateWindow(); // update before entering the tracker
  614.  
  615.     if (tracker.HitTest(point) == CRectTracker::hitMiddle) // moving, not sizing
  616.     {
  617.         // determine mouse position offset from the item itself
  618.         CRect rect = pItemHit->GetRect();
  619.         DocToClient(rect);
  620.         CPoint ptOffset(point.x - rect.left, point.y - rect.top);
  621.  
  622.         // determine sensitivity rectangle (determines when drag starts)
  623.         CRect rectDrag(rect.left, rect.top, rect.left+1, rect.top+1);
  624.         // execute the drag/drop operation
  625.         m_bInDrag = TRUE;
  626.         ClientToScreen(&rect);  // must be in screen co-ordinates
  627.         ClientToScreen(&rectDrag);
  628.         DROPEFFECT dropEffect = pItemHit->DoDragDrop(rect, ptOffset,
  629.             TRUE, DROPEFFECT_COPY|DROPEFFECT_MOVE, &rectDrag);
  630. //TRACE1("dropEffect=%d\n",dropEffect);
  631.         if (m_bInDrag == FALSE) return;// move in same window
  632.             
  633.         m_bInDrag = FALSE;
  634.  
  635.         if (dropEffect == DROPEFFECT_MOVE)
  636.         {
  637.             // the item was moved (essentially a copy w/delete)
  638.             pItemHit->Invalidate();
  639.             if (m_pSelection == pItemHit)
  640.                 m_pSelection = NULL;
  641.             GetDocument()->DeleteItem(pItemHit);
  642.         }
  643.     }
  644.     else
  645.     if (tracker.Track(this, point))
  646.     {
  647.         ClientToDoc(tracker.m_rect);
  648.         pItemHit->Move(tracker.m_rect);
  649.         GetDocument()->SetModifiedFlag();
  650.     }
  651.     
  652.     CScrollView::OnLButtonDown(nFlags, point);
  653. }
  654.  
  655.  
  656.  
  657.  
  658. BOOL CMainView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  659. {
  660.     if (pWnd == this && m_pSelection != NULL)
  661.     {
  662.         // give the tracker for the selection a chance
  663.         CRectTracker tracker;
  664.         SetupTracker(&tracker, m_pSelection);
  665.         if (tracker.SetCursor(this, nHitTest))
  666.             return TRUE;
  667.     }
  668.     return CScrollView::OnSetCursor(pWnd, nHitTest, message);
  669. }
  670.  
  671. /////////////////////////////////////////////////////////////////////////////
  672. // support for drag/drop
  673. void CMainView::DoPasteNative(
  674.     COleDataObject* pDataObject, CPoint* pPoint, CRectItem* pItem)
  675. {
  676.     // get file refering to clipboard data
  677.     CFile* pFile = pDataObject->GetFileData(CMainDoc::m_cfPrivate);
  678.     if (pFile == NULL)
  679.         {
  680.         // if the file failed to open, throw an exception
  681.         // to force cleanup in DoPasteItem.  the exact
  682.         // type of exception thrown here is unimportant...
  683.  
  684.         AfxThrowFileException(CFileException::generic);
  685.         }
  686.  
  687.     CArchive ar(pFile, CArchive::load);
  688.     TRY
  689.     {
  690.         // connect the file to an archive and read the data
  691.         ar.m_pDocument = GetDocument(); // for COleClientItem serialize
  692.         pItem->Serialize(ar);
  693.     }
  694.     CATCH_ALL(e)
  695.     {
  696.         ar.Close();
  697.         delete pFile;
  698.         THROW_LAST();
  699.     }
  700.     END_CATCH_ALL
  701.  
  702.     ar.Close();
  703.     delete pFile;
  704.  
  705.     // adjust position to that specified by point
  706.     if (pPoint != NULL)
  707.         pItem->m_ptPos = *pPoint;
  708. }
  709.  
  710. void CMainView::DoPasteStandard(BOOL bLink, COleDataObject* pDataObject,
  711.     CPoint* pPoint, CRectItem* pItem, CLIPFORMAT cfFormat)
  712. {
  713.     if (bLink)      // paste link
  714.     {
  715.         if (!pItem->CreateLinkFromData(pDataObject))
  716.             AfxThrowMemoryException();  // any exception will do
  717.     }
  718.     // paste embedded
  719.     else if (!pItem->CreateFromData(pDataObject) &&
  720.         !pItem->CreateStaticFromData(pDataObject, OLERENDER_DRAW, cfFormat))
  721.     {
  722.         AfxThrowMemoryException();      // any exception will do
  723.     }
  724.  
  725.     // copy the current iconic representation
  726.     FORMATETC fmtetc;
  727.     fmtetc.cfFormat = CF_METAFILEPICT;
  728.     fmtetc.dwAspect = DVASPECT_ICON;
  729.     fmtetc.ptd = NULL;
  730.     fmtetc.tymed = TYMED_MFPICT;
  731.     fmtetc.lindex = 1;
  732.     HGLOBAL hObj = pDataObject->GetGlobalData(CF_METAFILEPICT, &fmtetc);
  733.     if (hObj != NULL)
  734.     {
  735.         pItem->SetIconicMetafile(hObj);
  736.         // the following code is an easy way to free a metafile pict
  737.         STGMEDIUM stgMed;
  738.         memset(&stgMed, 0, sizeof(stgMed));
  739.         stgMed.tymed = TYMED_MFPICT;
  740.         stgMed.hGlobal = hObj;
  741.         ReleaseStgMedium(&stgMed);
  742.     }
  743.  
  744.     // set the current drawing aspect
  745.     hObj = pDataObject->GetGlobalData(m_cfObjectDescriptor);
  746.     if (hObj != NULL)
  747.     {
  748.         ASSERT(hObj != NULL);
  749.         // got CF_OBJECTDESCRIPTOR ok.  Lock it down and extract size.
  750.         LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObj);
  751.         ASSERT(pObjDesc != NULL);
  752.         pItem->SetDrawAspect((DVASPECT)pObjDesc->dwDrawAspect);
  753.         GlobalUnlock(hObj);
  754.         GlobalFree(hObj);
  755.     }
  756.  
  757.     // set top-left based on point of drop
  758.     if (pPoint != NULL)
  759.         pItem->m_ptPos = *pPoint;
  760.  
  761.     // get size from drag/drop operation
  762.     CSize size;
  763.     if (GetObjectInfo(pDataObject, &size, NULL) && size.cx != 0 && size.cy != 0)
  764.     {
  765.         // use size obtained from object instead of default
  766.         size.cx = MulDiv(size.cx, 10, 254);
  767.         size.cy = -MulDiv(size.cy, 10, 254);
  768.         pItem->SetSize(size);
  769.         CSize sizeExtent;
  770.         pItem->GetCachedExtent(&sizeExtent);
  771.         pItem->SetBaseSize(sizeExtent);
  772.     }
  773.     else
  774.     {
  775.         // no extent from CF_OBJECTDESCRIPTOR, use extent from object
  776.         pItem->UpdateExtent();
  777.     }
  778. }
  779.  
  780.  
  781. // Helper for paste/pastelink
  782. //
  783. //                  bLink       pDataObject     pPoint              cfFormat
  784. //  EditPaste       FALSE       NULL(clipboard) NULL(default)       0
  785. //  Drag/Drop       TRUE/FALSE  X               X                   0
  786. //  PasteLink       TRUE        NULL(clipboard) NULL(default)       0
  787. //  PasteSpecial    TRUE/FALSE  X               NULL(default)       X
  788. CRectItem* CMainView::DoPasteItem(BOOL bLink, COleDataObject* pDataObject,
  789.     CPoint* pPoint, CLIPFORMAT cfFormat)
  790. {
  791.     BeginWaitCursor();
  792.  
  793.     CRectItem* pItem = GetDocument()->CreateItem();
  794.     ASSERT_VALID(pItem);
  795.     BOOL bAllowAdjust = (pPoint == NULL) ? TRUE : FALSE;
  796.  
  797.     // use clipboard data if not doing drag/drop
  798.     COleDataObject clipboardData;
  799.     if (pDataObject == NULL)
  800.     {
  801.         clipboardData.AttachClipboard();
  802.         pDataObject = &clipboardData;
  803.     }
  804.  
  805.     TRY
  806.     {
  807.         if (cfFormat == CMainDoc::m_cfPrivate)
  808.         {
  809.             // if format specified (i.e. PasteSpecial) then use that one
  810.             DoPasteNative(pDataObject, pPoint, pItem);
  811.         }
  812.         else if (!bLink && cfFormat == 0 &&
  813.             pDataObject->IsDataAvailable(CMainDoc::m_cfPrivate))
  814.         {
  815.             // if we're not pasting a link, cfFormat was unspecified,
  816.             // and private format is available use it
  817.             DoPasteNative(pDataObject, pPoint, pItem);
  818.         }
  819.         // otherwise perform a standard paste
  820.         else if (bAllowAdjust)
  821.         {
  822.             CPoint ptDef(10, -10);
  823.             DoPasteStandard(bLink, pDataObject, &ptDef, pItem, cfFormat);
  824.         }
  825.         else
  826.         {
  827.             DoPasteStandard(bLink, pDataObject, pPoint, pItem, cfFormat);
  828.         }
  829.  
  830.         if (bAllowAdjust)
  831.         {
  832.             // allow document to adjust position of item so that it doesn't
  833.             // lay directly over an item of the same size
  834.             // this only occurs if the drop point is not specified
  835.             GetDocument()->AdjustItemPosition(pItem);
  836.         }
  837.  
  838.     }
  839.     CATCH_ALL(e)
  840.     {
  841.         // general cleanup
  842.         TRACE0("failed to embed/link an OLE object\n");
  843.         pItem->Delete();
  844.         pItem = NULL;
  845.     }
  846.     END_CATCH_ALL
  847.  
  848.     // set the selection with bSafeSelect = TRUE
  849.     SetSelection(pItem, TRUE);
  850.  
  851.     // update the document and views
  852.     GetDocument()->SetModifiedFlag();
  853.     GetDocument()->UpdateAllViews(NULL, 0, pItem);      // including this view
  854.  
  855.     EndWaitCursor();
  856.  
  857.     return pItem;
  858. }
  859.  
  860. /////////////////////////////////////////////////////////////////////////////
  861. // support for drag/drop
  862. int CMainView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  863. {
  864.     if (CScrollView::OnCreate(lpCreateStruct) == -1)
  865.         return -1;
  866.     
  867.     // register drop target
  868.     m_dropTarget.Register(this);
  869.     
  870.     return 0;
  871. }
  872.  
  873. BOOL CMainView::OnDrop(COleDataObject* pDataObject,
  874.     DROPEFFECT dropEffect, CPoint point)
  875. {
  876.     ASSERT_VALID(this);
  877.  
  878.     // clean up focus rect
  879.     OnDragLeave();
  880.  
  881.     // offset point as appropriate for dragging
  882.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  883.     CClientDC dc(NULL);
  884.     dc.HIMETRICtoDP(&m_dragSize);
  885.     dc.HIMETRICtoDP(&m_dragOffset);
  886.     point -= m_dragOffset;
  887.  
  888.     // if move within the view
  889.     ClientToDoc(point);
  890.     if ((dropEffect & DROPEFFECT_MOVE) && m_bInDrag)
  891.     {
  892.         ASSERT(m_pSelection != NULL);
  893.         m_bInDrag = FALSE; // signal drag code that a move happened
  894.         // set top-left based on point of drop
  895.         CRect rect = m_pSelection->GetRect();
  896.         if (rect.TopLeft() != point) // if moved
  897.         {
  898.             m_pSelection->Move(CRect(point,rect.Size()));
  899.             GetDocument()->SetModifiedFlag();
  900.         }
  901.     }
  902.  
  903.     // check and paste link
  904.     else if ((dropEffect & DROPEFFECT_LINK) && DoPasteItem(TRUE, pDataObject, &point))
  905.         return TRUE;
  906.  
  907.     // paste embedding/static
  908.     else if (DoPasteItem(FALSE, pDataObject, &point))
  909.         return TRUE;
  910.  
  911.     return FALSE;
  912. }
  913.  
  914.  
  915. BOOL CMainView::GetObjectInfo(COleDataObject* pDataObject,
  916.     CSize* pSize, CSize* pOffset)
  917. {
  918.     ASSERT(pSize != NULL);
  919.  
  920.     // get object descriptor data
  921.     HGLOBAL hObjDesc = pDataObject->GetGlobalData(m_cfObjectDescriptor);
  922.     if (hObjDesc == NULL)
  923.     {
  924.         if (pOffset != NULL)
  925.             *pOffset = CSize(0, 0); // fill in defaults instead
  926.         *pSize = CSize(0, 0);
  927.         return FALSE;
  928.     }
  929.     ASSERT(hObjDesc != NULL);
  930.  
  931.     // otherwise, got CF_OBJECTDESCRIPTOR ok.  Lock it down and extract size.
  932.     LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObjDesc);
  933.     ASSERT(pObjDesc != NULL);
  934.     pSize->cx = (int)pObjDesc->sizel.cx;
  935.     pSize->cy = (int)pObjDesc->sizel.cy;
  936.     if (pOffset != NULL)
  937.     {
  938.         pOffset->cx = (int)pObjDesc->pointl.x;
  939.         pOffset->cy = (int)pObjDesc->pointl.y;
  940.     }
  941.     GlobalUnlock(hObjDesc);
  942.     GlobalFree(hObjDesc);
  943.  
  944.     // successfully retrieved pSize & pOffset info
  945.     return TRUE;
  946. }
  947.  
  948. DROPEFFECT CMainView::OnDragEnter(COleDataObject* pDataObject,
  949.     DWORD grfKeyState, CPoint point)
  950. {
  951.     ASSERT(m_prevDropEffect == DROPEFFECT_NONE);
  952.  
  953.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  954.     CClientDC dc(NULL);
  955.     dc.HIMETRICtoDP(&m_dragSize);
  956.     dc.HIMETRICtoDP(&m_dragOffset);
  957.  
  958.     return OnDragOver(pDataObject, grfKeyState, point);
  959. }
  960.  
  961. DROPEFFECT CMainView::OnDragOver(COleDataObject*,
  962.     DWORD grfKeyState, CPoint point)
  963. {
  964.     point -= m_dragOffset;  // adjust target rect by original cursor offset
  965.  
  966.     // check for point outside logical area -- i.e. in hatched region
  967.     // GetTotalSize() returns the size passed to SetScrollSizes
  968.     CRect rectScroll(CPoint(0, 0), GetTotalSize());
  969.  
  970.     CRect rectItem(point,m_dragSize);
  971.     if (rectItem.IsRectEmpty())
  972.     {
  973.         // some apps might have a null size in the object descriptor...
  974.         rectItem.InflateRect(1,1);
  975.     }
  976.     rectItem.OffsetRect(GetDeviceScrollPosition());
  977.  
  978.     DROPEFFECT de = DROPEFFECT_NONE;
  979.     CRect rectTemp;
  980.     if (rectTemp.IntersectRect(rectScroll, rectItem))
  981.     {
  982.         // check for force link
  983.         if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  984.             de = DROPEFFECT_LINK;
  985.         // check for force copy
  986.         else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  987.             de = DROPEFFECT_COPY;
  988.         // check for force move
  989.         else if ((grfKeyState & MK_ALT) == MK_ALT)
  990.             de = DROPEFFECT_MOVE;
  991.         // default -- recommended action is move
  992.         else
  993.             de = DROPEFFECT_MOVE;
  994.     }
  995.  
  996.     if (point == m_dragPoint)
  997.         return de;
  998.  
  999.     // otherwise, cursor has moved -- need to update the drag feedback
  1000.     CClientDC dc(this);
  1001.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1002.     {
  1003.         // erase previous focus rect
  1004.         dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
  1005.     }
  1006.     m_prevDropEffect = de;
  1007.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1008.     {
  1009.         m_dragPoint = point;
  1010.         dc.DrawFocusRect(CRect(point, m_dragSize));
  1011.     }
  1012.     return de;
  1013. }
  1014.  
  1015. void CMainView::OnDragLeave()
  1016. {
  1017.     CClientDC dc(this);
  1018.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1019.     {
  1020.         dc.DrawFocusRect(CRect(m_dragPoint,m_dragSize)); // erase previous focus rect
  1021.         m_prevDropEffect = DROPEFFECT_NONE;
  1022.     }
  1023. }
  1024.  
  1025. // for scroll with drop
  1026. BOOL CMainView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) 
  1027. {
  1028.     // remove drag/drop feedback before scrolling
  1029.     if (bDoScroll && m_prevDropEffect != DROPEFFECT_NONE)
  1030.     {
  1031.         CClientDC dc(this);
  1032.         dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
  1033.             // erase previous focus rect
  1034.         m_prevDropEffect = DROPEFFECT_NONE;
  1035.     }
  1036.  
  1037.     // do the scroll
  1038.     if (!CScrollView::OnScrollBy(sizeScroll, bDoScroll))
  1039.         return FALSE;
  1040.  
  1041.     // update the position of any in-place active item
  1042.     if (bDoScroll)
  1043.     {
  1044.         UpdateActiveItem();
  1045.         UpdateWindow();
  1046.     }
  1047.  
  1048.     return TRUE;
  1049. }
  1050.  
  1051.  
  1052. /////////////////////////////////////////////////////////////////////////////
  1053. // Main 'Edit' menu commands
  1054. void CMainView::OnUpdateEditMenu(CCmdUI* pCmdUI)
  1055. {
  1056.     // most Edit menu commands are enabled only if we have a selection
  1057.     //  and there are no in-place activations for this view
  1058.     pCmdUI->Enable(m_pSelection != NULL &&
  1059.         GetDocument()->GetInPlaceActiveItem(this) == NULL);
  1060. }
  1061. void CMainView::OnUpdateEditPaste(CCmdUI* pCmdUI)
  1062. {
  1063.     // determine if private or standard OLE formats are on the clipboard
  1064.     COleDataObject dataObj;
  1065.     BOOL bEnable = dataObj.AttachClipboard() &&
  1066.         (dataObj.IsDataAvailable(CMainDoc::m_cfPrivate) ||
  1067.          COleClientItem::CanCreateFromData(&dataObj));
  1068.  
  1069.     // enable command based on availability
  1070.     pCmdUI->Enable(bEnable);
  1071. }
  1072.  
  1073.  
  1074. void CMainView::OnUpdateEditClearAll(CCmdUI* pCmdUI) 
  1075. {
  1076.     CMainDoc* pDoc = GetDocument();
  1077.     ASSERT_VALID(pDoc);
  1078.     BOOL bEnable = (pDoc->GetStartPosition() != NULL);
  1079.     pCmdUI->Enable(bEnable);
  1080. }
  1081.  
  1082.  
  1083. void CMainView::OnEditClear()
  1084. {
  1085.     if (m_pSelection != NULL)
  1086.     {
  1087.         CRectItem* pItem = m_pSelection;
  1088.         m_pSelection = NULL;
  1089.         GetDocument()->DeleteItem(pItem);
  1090.     }
  1091. }
  1092.  
  1093.  
  1094. void CMainView::OnEditCut()
  1095. {
  1096.     ASSERT(m_pSelection != NULL);
  1097.     TRY
  1098.     {
  1099.         m_pSelection->CopyToClipboard(TRUE);
  1100.         OnEditClear();
  1101.     }
  1102.     CATCH_ALL(e)
  1103.     {
  1104.         AfxMessageBox(IDP_CLIPBOARD_CUT_FAILED);
  1105.     }
  1106.     END_CATCH_ALL
  1107. }
  1108.  
  1109. void CMainView::OnEditCopy()
  1110. {
  1111.     ASSERT(m_pSelection != NULL);
  1112.     TRY
  1113.     {
  1114.         m_pSelection->CopyToClipboard(TRUE);
  1115.     }
  1116.     CATCH_ALL(e)
  1117.     {
  1118.         AfxMessageBox(IDP_CLIPBOARD_COPY_FAILED);
  1119.     }
  1120.     END_CATCH_ALL
  1121. }
  1122.  
  1123. void CMainView::OnPaste()
  1124. {
  1125.     if (DoPasteItem(FALSE, NULL, NULL) == NULL)
  1126.         AfxMessageBox(IDP_GET_FROM_CLIPBOARD_FAILED);
  1127. }
  1128.  
  1129. void CMainView::OnEditPasteInview() 
  1130. {
  1131.     if (DoPasteItem(FALSE, NULL, &m_pointMouse) == NULL)
  1132.         AfxMessageBox(IDP_GET_FROM_CLIPBOARD_FAILED);
  1133. }
  1134.  
  1135.  
  1136. void CMainView::OnObjectResetsize()
  1137. {
  1138.     ASSERT(m_pSelection != NULL);
  1139.     m_pSelection->ResetSize();
  1140. }
  1141.  
  1142.  
  1143. void CMainView::ClearAll() 
  1144. {
  1145.     CMainDoc* pDoc = GetDocument();
  1146.     ASSERT_VALID(pDoc);
  1147.     m_pSelection = NULL;
  1148.  
  1149.     POSITION pos = pDoc->GetStartPosition();
  1150.     while (pos != NULL)
  1151.     {
  1152.         CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
  1153.         if (pItem != NULL)
  1154.         {
  1155.             GetDocument()->DeleteItem(pItem);
  1156.         }
  1157.     }
  1158.  
  1159. }
  1160.  
  1161. void CMainView::OnEditClearAll() 
  1162. {
  1163.     ClearAll(); 
  1164. }
  1165.  
  1166.  
  1167.  
  1168. void CMainView::OnMouseMove(UINT nFlags, CPoint point) 
  1169. {
  1170.     CScrollView::OnMouseMove(nFlags, point);
  1171.     ClientToDoc(point);
  1172.     CString str;
  1173.     str.Format("X %d, Y %d",(int)(point.x*0.254), -(int)(point.y*0.254));
  1174.     ((CMainFrame*)GetParent())->IndicatorMouse(str);
  1175. }
  1176.  
  1177. void CMainView::OnViewNet() 
  1178. {
  1179.     m_bIsNet = !m_bIsNet;
  1180.     Invalidate();
  1181. }
  1182.  
  1183. void CMainView::OnUpdateViewNet(CCmdUI* pCmdUI) 
  1184. {
  1185.     pCmdUI->SetCheck(m_bIsNet); 
  1186. }
  1187.  
  1188.  
  1189. // set new size to item
  1190. // size in 0.01 ∞∞
  1191. //
  1192. void CMainView::SelectionSetSize(CSize &size) 
  1193. {
  1194.     if (m_pSelection != NULL) 
  1195.     {
  1196.         CSize sizeNew(MulDiv(size.cx, 10, 254), - MulDiv(size.cy, 10, 254));
  1197.         m_pSelection->SetSize(sizeNew);
  1198.         m_pSelection->SetBaseSize(sizeNew);
  1199.     }
  1200.     UpdateActiveItem();
  1201. }
  1202.  
  1203. /////////////////////////////////////////////////////////////////////////////
  1204. void CMainView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
  1205. {
  1206.     if (pHint == NULL && lHint == 0)
  1207.     {
  1208.         // some sort of clear all
  1209.         m_pSelection = NULL;
  1210.     }
  1211.  
  1212.     if (pHint != NULL && pHint->IsKindOf(RUNTIME_CLASS(CRectItem)))
  1213.     {
  1214.         // just invalidate the one item
  1215.         InvalidateItem((CRectItem*)pHint);
  1216.  
  1217.         // clear selection if pointing to deleted item
  1218.         if (lHint == 1 && pHint == m_pSelection)
  1219.         {
  1220.             // specific case of pHint being deleted
  1221.             m_pSelection = NULL;
  1222.         }
  1223.     }
  1224.     else if (lHint != 0)
  1225.     {
  1226.         // invalidate arbitrary rectangle
  1227.         InvalidateRect((CRect*)lHint);
  1228.     }
  1229.     else
  1230.     {
  1231.         // complete update
  1232.         CScrollView::OnUpdate(pSender, lHint, pHint);
  1233.     }
  1234. }
  1235.  
  1236.  
  1237. /////////////////////////////////////////////////////////////////////////////
  1238. // Insert new object (use for Excel or FindGraph)
  1239. // x,y  - top left pos in 0.01 inch
  1240. // return FALSE if object unregistered
  1241. //
  1242. BOOL CMainView::InsertObject(CLSID clsid, int x, int y) 
  1243. {
  1244.     BOOL bResult = FALSE;
  1245.     BeginWaitCursor();
  1246.     CRectItem* pItem = NULL;
  1247.     TRY
  1248.     {
  1249.         CMainDoc* pDoc = GetDocument();
  1250.         pItem = new CRectItem(pDoc, x, y);
  1251.         ASSERT_VALID(pItem);
  1252.  
  1253.         if (!pItem->CreateNewItem(clsid))
  1254.             AfxThrowMemoryException();  // any exception will do
  1255.  
  1256.         // make sure we deactivate any active items first.
  1257.         COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  1258.         if (pActiveItem != NULL)
  1259.             pActiveItem->Deactivate();
  1260.  
  1261.  
  1262.         pItem->DoVerb(OLEIVERB_SHOW, this);
  1263.  
  1264.         ASSERT_VALID(pItem);
  1265.         m_pSelection = pItem;   // set selection to last inserted item
  1266.         pDoc->UpdateAllViews(NULL);
  1267.         bResult = TRUE;
  1268.     }
  1269.     CATCH_ALL(e)
  1270.     {
  1271.         if (pItem != NULL)
  1272.         {
  1273.             ASSERT_VALID(pItem);
  1274.             pItem->Delete();
  1275.         }
  1276.     }
  1277.     END_CATCH_ALL
  1278. /*
  1279. CString str;
  1280. pItem->GetUserType(USERCLASSTYPE_FULL, str); TRACE("\nUSERCLASSTYPE_FULL = ");TRACE(str);
  1281. pItem->GetUserType(USERCLASSTYPE_SHORT, str); TRACE("\nUSERCLASSTYPE_SHORT = ");TRACE(str);
  1282. pItem->GetUserType(USERCLASSTYPE_APPNAME, str); TRACE("\nUSERCLASSTYPE_APPNAME = ");TRACE(str);
  1283. */
  1284.     return bResult;
  1285. }
  1286.  
  1287.  
  1288.  
  1289.  
  1290. #pragma warning( disable : 4305 )
  1291. #pragma warning( disable : 4309 )
  1292.  
  1293. // Quick insert FiindGraph (fgr) object
  1294. // use clsidFindGraph,
  1295. //
  1296. static const CLSID clsidFindGraph =
  1297. { 0x5c0cac3e, 0x8202, 0x4491, { 0x8a, 0xd, 0x29, 0x87, 0xea7, 0xed, 0xd7, 0xfe } };
  1298. void CMainView::OnInsertFindGraph() 
  1299. {
  1300.     if (!InsertObject(clsidFindGraph))
  1301.         AfxMessageBox(IDP_FAINDGRAPH_FAILED);
  1302. }
  1303.  
  1304.  
  1305. // Insert Excel sheet
  1306. //
  1307. void CMainView::OnInsertExcel() 
  1308. {
  1309.     CLSID clsid;
  1310.     if(FAILED(::CLSIDFromProgID(L"Excel.sheet",&clsid)))
  1311.     {
  1312.         AfxMessageBox(IDP_EXCEL_FAILED);    
  1313.         return;
  1314.     }
  1315.  
  1316.     // Let's arrange a sheet Excel to the right of FindGraph
  1317.     if (InsertObject(clsid, int(1050/2.54), 0))
  1318.     {
  1319.  
  1320.  
  1321.     }else
  1322.         AfxMessageBox(IDP_EXCEL_FAILED);
  1323.  
  1324. }
  1325.  
  1326.  
  1327.  
  1328. ///////////////////////////////////////////////////////////////
  1329. // How to realise automation FindGraph.
  1330. // 1. Create IFindGraph wrapper class from a type FindGraph.tlb
  1331. // 2. Add #include "FindGraph.h"
  1332. //
  1333. // 3. Add to CRectItem:
  1334. //               LPDISPATCH GetIDispatch();
  1335. //    This returns IDispatch* for embedded application
  1336. //    see sample from MSDN: HOWTO: IQ: Q184663 for details
  1337. //
  1338. // 4. Call FindGraphs's methods as wrapper:
  1339. //        DECLARE_FINDGRAPHS(FindGraph);
  1340. //        FindGraph.ReleaseDispatch();
  1341. //
  1342. //
  1343. //
  1344. //
  1345. //
  1346. //
  1347. ///////////////////////////////////////////////////////////////
  1348. // nColor  - color number
  1349. //  0        BLACK
  1350. //  1        BLUE 
  1351. //  2        GREEN
  1352. //  3        RED  
  1353. //  4        BROWN
  1354. //  5        GRAY 
  1355. //
  1356. // nShape  - marker
  1357. //  0        RECT (CROSS)
  1358. //  1        TRIA
  1359. //    2        CIRC
  1360. //
  1361. // nWidth  - X radius,  0,1 mm
  1362. // fAspect - aspect ratio Y/X
  1363.  
  1364. ///////////////////////////////////////////////////////////////
  1365. // IDispatch* for embedded application
  1366. //
  1367. LPDISPATCH CMainView::GetIDispatch()
  1368. {
  1369.     if (m_pSelection != NULL) 
  1370.         return m_pSelection->GetIDispatch();
  1371.     return NULL;
  1372. }
  1373.  
  1374. //start define--------------------------
  1375. #define DECLARE_FINDGRAPHS(FindGraphs) \
  1376.     if (m_pSelection==NULL) return;\
  1377.     m_pSelection->DoVerb(OLEIVERB_SHOW, this);\
  1378.     LPDISPATCH lpDisp = GetIDispatch();\
  1379.     if (lpDisp == NULL)    return;\
  1380.     IFindGraph FindGraphs;\
  1381.     FindGraphs.AttachDispatch(lpDisp);\
  1382. //----------------------------end define
  1383.  
  1384.  
  1385. // How to add at some points to new series
  1386. //
  1387. void CMainView::FindGraphsSet() 
  1388. {
  1389.     DECLARE_FINDGRAPHS(FindGraph);
  1390.     
  1391.         CString str; 
  1392.         long    dwId;
  1393.         short    nColor = 1,
  1394.                 nShape = 2, 
  1395.                 nWidth =25;
  1396.         double  fAspect = 1.;
  1397.         CString strName = _T("By one");
  1398.    
  1399.         // Create new series 
  1400.         dwId = FindGraph.DotsNew(nColor, nShape, nWidth, fAspect, strName);
  1401.         m_dwIdDots = dwId;
  1402.         if (dwId >= 0)
  1403.         {
  1404.             // How to add single point to series with dwId
  1405.             int n = 20;
  1406.             for (int i=0; i<n; i++)
  1407.             {
  1408.                 double    fX = 1. + 0.25*i,
  1409.                         fY = 7. - 0.35*i,
  1410.                         fZ = i;
  1411.                 FindGraph.DotsAddPoint(dwId, fX, fY, fZ);
  1412.                 // Optionally: paint appearance of each point
  1413.                 FindGraph.DotsUpdate(dwId);
  1414.             }
  1415.  
  1416.         }
  1417.  
  1418.         // To add at once some points 
  1419.         // Create new series 
  1420.         // dwId - identifier of a series
  1421.         dwId = FindGraph.DotsNew(2, 1, 20, 1, _T("At once"));
  1422.         m_dwIdDots = dwId;
  1423.         if (dwId >= 0)
  1424.         {
  1425.             int n = 1000;
  1426.             int nParam = 3;
  1427.             // If nParam==3  (x, y, z),  if nParam==2 - x, y only
  1428.             // One dimensional array with n*nParam elements zero-based indexing
  1429.             SAFEARRAYBOUND    bounds[1]; 
  1430.                             bounds[0].cElements = n*nParam;
  1431.                             bounds[0].lLbound = 0;
  1432.             // Allocate the memory for the descriptor and the array data
  1433.             SAFEARRAY *psa = SafeArrayCreate(VT_R8, 1, bounds);
  1434.             if (psa)
  1435.             {
  1436.                 psa->fFeatures  = FADF_AUTO|FADF_FIXEDSIZE;
  1437.                 double *pr;
  1438.                 SafeArrayAccessData(psa, (void**)&pr);
  1439.                     // Initialize each element
  1440.                     int  ip=0;
  1441.                     for (int i = 0; i < n; i++)
  1442.                     {
  1443.                         double  fi = 2.*3.14159/n*i;
  1444.                         double    fX = 4.+3.*sin(fi),
  1445.                                 fY = 3.+2.*cos(fi),
  1446.                                 fZ = i;
  1447.                         pr[ip++] = fX;
  1448.                         pr[ip++] = fY;
  1449.                         pr[ip++] = fZ;
  1450.                     }
  1451.                 SafeArrayUnaccessData(psa);// release lock on array state
  1452.                 // Create a VARIANT that contains our safearray
  1453.                 VARIANT var; ZeroMemory(&var, sizeof(var));
  1454.                         var.vt = VT_UI1 | VT_ARRAY;
  1455.                         var.parray = psa;
  1456.                 FindGraph.DotsAddPoints(dwId, nParam, var);
  1457.             }
  1458.  
  1459.             FindGraph.DotsUpdate(dwId); 
  1460.         }
  1461.    FindGraph.ReleaseDispatch();
  1462. }
  1463.  
  1464.  
  1465. // How to get points selected 
  1466. //
  1467. void CMainView::FindGraphsGet() 
  1468. {
  1469.     DECLARE_FINDGRAPHS(FindGraph);
  1470.  
  1471.         // Copy selected points (X, Y, Z) and put it on the buffer.
  1472.         long n = FindGraph.SelectedGetStart(0); 
  1473.         if  (n)
  1474.         {
  1475.             if (n<10) 
  1476.             {
  1477.                 CDot dot;
  1478.                 // In cycle we choose points:
  1479.                 while (FindGraph.SelectedGetDot(&dot.m_fX, &dot.m_fY, &dot.m_fZ)==S_OK)
  1480.                 {
  1481.                      // There can be your operatings with points here
  1482.                      // For example to transfer them to Excel sheet
  1483.                     TRACE("x=%f y=%f z=%f\n", dot.m_fX, dot.m_fY, dot.m_fZ);
  1484.                     
  1485.                 }
  1486.             }
  1487.             // How to get whole array of selected points at once
  1488.             else 
  1489.             {
  1490.                 int nParam = 3; // x, y, z
  1491.                 SAFEARRAYBOUND    bounds[1]; 
  1492.                                 bounds[0].cElements = n*nParam;
  1493.                                 bounds[0].lLbound = 0;
  1494.                 // Allocate the memory for the descriptor and the array data
  1495.                 SAFEARRAY *psa = SafeArrayCreate(VT_R8, 1, bounds);
  1496.                 if (psa)
  1497.                 {
  1498.                     psa->fFeatures  = FADF_FIXEDSIZE; // NOTE: not FADF_AUTO
  1499.                     // Create a VARIANT that contains our safearray
  1500.                     VARIANT var; ZeroMemory(&var, sizeof(var));
  1501.                             var.vt = VT_UI1 | VT_ARRAY;
  1502.                             var.parray = psa;
  1503.                             
  1504.                     // Fill array with points (X, Y, Z).
  1505.                     if (FindGraph.SelectedGetDots(nParam, &var)==S_OK)
  1506.                     {
  1507.  
  1508.                         double *pr;
  1509.                         SafeArrayAccessData(psa, (void**)&pr);
  1510.                             int  ip=0;
  1511.                             // If nParam==3 Points by triples (X, Y, Z)
  1512.                             // If nParam==2 Points by couples (X, Y)
  1513.                             for (int i = 0; i < n; i++)
  1514.                             {
  1515.                                 double    fX = pr[ip  ],
  1516.                                         fY = pr[ip+1],
  1517.                                         fZ = (nParam==3) ? pr[ip+2] : 0;
  1518.                                 ip+=nParam;
  1519.                                 // There can be your operatings with points here
  1520.                                 TRACE("x=%f y=%f\n",fX, fY);
  1521.                             }
  1522.                         // Release lock on array state
  1523.                         SafeArrayUnaccessData(psa);
  1524.                     }
  1525.                 }
  1526.                 // Free buffer memory
  1527.                 n = FindGraph.SelectedGetStop(0); 
  1528.             }
  1529.         }
  1530.  
  1531.     FindGraph.ReleaseDispatch();
  1532. }
  1533.  
  1534.  
  1535. // The example how to change plot properties
  1536. //
  1537. void CMainView::FindGraphsParams() 
  1538. {
  1539.     // The identifier of a series
  1540.     DWORD dwId = m_dwIdDots;
  1541.     DECLARE_FINDGRAPHS(FindGraph);
  1542.  
  1543.         // Item (FindGraph plot) size, 0,01 mm
  1544.         CSize size (12000, 8000);
  1545.         // Set new size to item
  1546.         SelectionSetSize(size);
  1547.  
  1548.         FindGraph.SetDocWidth (size.cx/10); // 0,1 mm
  1549.         FindGraph.SetDocHeight(size.cy/10);
  1550.  
  1551.         FindGraph.SetDocTitle  (_T("From Crov title"));
  1552.         FindGraph.SetDocComment(_T("From Crov comment"));
  1553.         FindGraph.SetAxeXname (_T("Xname"));
  1554.         FindGraph.SetAxeXunit (_T("Xunit"));
  1555.         FindGraph.SetAxeXstart(-5.); // In X units
  1556.         FindGraph.SetAxeXscale( 2.); // Ratio: X units / sm
  1557.         FindGraph.SetAxeYname (_T("Yname"));
  1558.         FindGraph.SetAxeYunit (_T("Yunit"));
  1559.         FindGraph.SetAxeYstart(-2.); // In Y units
  1560.         FindGraph.SetAxeYscale( 2.); // Ratio: Y units / sm
  1561.  
  1562.  
  1563.         if (dwId >= 0)
  1564.         {
  1565.             CString str; 
  1566.             short    nColor = 1,
  1567.                     nShape = 2, 
  1568.                     nWidth =25;
  1569.             double  fAspect = 1.;
  1570.  
  1571.             // Get color number of points in series
  1572.             short nColorGet=0;
  1573.             if (FindGraph.DotsColorNumGet(dwId, &nColorGet)==S_OK)
  1574.             {
  1575.                 str.Format("nColorGet=%d",nColorGet);
  1576.                 //AfxMessageBox(str);    
  1577.             }
  1578.             nColor=nColorGet+1;
  1579.             // Set new color number
  1580.             FindGraph.DotsColorNumSet(dwId, nColor); 
  1581.  
  1582.  
  1583.             // Get number of marker 
  1584.             short nShapeGet=0;
  1585.             if (FindGraph.DotsShapeGet(dwId, &nShapeGet)==S_OK)
  1586.             {
  1587.                 //str.Format("nShapeGet=%d",nShapeGet);
  1588.                 //AfxMessageBox(str);    
  1589.             }
  1590.             nShape=nShapeGet+1;
  1591.             // Set new number of marker 
  1592.             FindGraph.DotsShapeSet(dwId, nShape); 
  1593.  
  1594.  
  1595.             // Get radius of circle point
  1596.             short nWidthGet=10;
  1597.             if (FindGraph.DotsWidthGet(dwId, &nWidthGet)==S_OK)
  1598.             {
  1599.                 //str.Format("nWidthGet=%d",nWidthGet);
  1600.                 //AfxMessageBox(str);    
  1601.             }
  1602.             nWidthGet*=2; 
  1603.             if (nWidthGet > 50)
  1604.                 nWidthGet = 5;
  1605.             // Set new radius of circle point
  1606.             FindGraph.DotsWidthSet(dwId, nWidthGet); 
  1607.  
  1608.             // Get aspect ratio: (Height Y) / (Width X); 
  1609.             double fAspectGet=1;
  1610.             if (FindGraph.DotsAspectGet(dwId, &fAspectGet)==S_OK)
  1611.             {
  1612.                 //str.Format("fAspectGet=%f",fAspectGet);
  1613.                 //AfxMessageBox(str);    
  1614.             }
  1615.             fAspectGet*=2; 
  1616.             if (fAspectGet > 10.)
  1617.                 fAspectGet = 0.25;
  1618.             // Set new aspect ratio
  1619.             FindGraph.DotsAspectSet(dwId, fAspectGet); 
  1620.  
  1621.             // Get title of a series 
  1622.             CString strNameGet;
  1623.             //_bstr_t bstr; 
  1624.             BSTR bstr = strNameGet.AllocSysString();
  1625.             if (FindGraph.DotsNameGet(dwId, &bstr)==S_OK)
  1626.             {
  1627.                 strNameGet = CString(bstr);
  1628.                 //AfxMessageBox(strNameGet);    
  1629.             }
  1630.             strNameGet = "new name";
  1631.             // Set new title of a series 
  1632.             FindGraph.DotsNameSet(dwId, strNameGet); 
  1633.  
  1634.             // Assigns to connect points with line 
  1635.             FindGraph.DotsShowLine(dwId, 1);
  1636.             
  1637.     // Next samples:            
  1638.     // How to get RGB value for number of color
  1639.     //   long color = FindGraph.DotsColor(1); 
  1640.     
  1641.         }
  1642.         FindGraph.DocUpdate();
  1643.     FindGraph.ReleaseDispatch();
  1644. }
  1645.  
  1646.  
  1647. ////////////////////////////////////////////////////
  1648.  
  1649. void CMainView::OnUpdateItemDots(CCmdUI* pCmdUI) 
  1650. {
  1651.     BOOL bEnable = FALSE;
  1652.     if (m_pSelection != NULL) 
  1653.     {
  1654.         CLSID clsid; m_pSelection->GetClassID(&clsid);
  1655.         bEnable = (clsid==clsidFindGraph);
  1656.     }
  1657.     pCmdUI->Enable(bEnable);
  1658. }
  1659.  
  1660. void CMainView::OnItemDots() 
  1661. {
  1662.     FindGraphsSet(); 
  1663. }
  1664.  
  1665. void CMainView::OnItemDotsget() 
  1666. {
  1667.     FindGraphsGet();
  1668. }
  1669.  
  1670.  
  1671. void CMainView::OnItemFindGraphProp() 
  1672. {
  1673.     FindGraphsParams();
  1674. }
  1675.  
  1676.  
  1677.  
  1678.